home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Source / GNU / libg++ / libiberty / strtoul.c < prev    next >
C/C++ Source or Header  |  1994-02-15  |  2KB  |  98 lines

  1. /*
  2.  * strtol : convert a string to long.
  3.  *
  4.  * Andy Wilson, 2-Oct-89.
  5.  */
  6.  
  7. #include <errno.h>
  8. #include <ctype.h>
  9. #include <stdio.h>
  10. #include "ansidecl.h"
  11.  
  12. #ifndef ULONG_MAX
  13. #define    ULONG_MAX    ((unsigned long)(~0L))        /* 0xFFFFFFFF */
  14. #endif
  15.  
  16. extern int errno;
  17.  
  18. unsigned long
  19. strtoul(s, ptr, base)
  20.      CONST char *s; char **ptr; int base;
  21. {
  22.   unsigned long total = 0;
  23.   unsigned digit;
  24.   CONST char *start=s;
  25.   int did_conversion=0;
  26.   int overflow = 0;
  27.   int negate = 0;
  28.   unsigned long maxdiv, maxrem;
  29.  
  30.   if (s==NULL)
  31.     {
  32.       errno = ERANGE;
  33.       if (!ptr)
  34.     *ptr = (char *)start;
  35.       return 0L;
  36.     }
  37.  
  38.   while (isspace(*s))
  39.     s++;
  40.   if (*s == '+')
  41.     s++;
  42.   else if (*s == '-')
  43.     s++, negate = 1;
  44.   if (base==0 || base==16) /*  the 'base==16' is for handling 0x */
  45.     {
  46.       int tmp;
  47.  
  48.       /*
  49.        * try to infer base from the string
  50.        */
  51.       if (*s != '0')
  52.         tmp = 10;    /* doesn't start with 0 - assume decimal */
  53.       else if (s[1] == 'X' || s[1] == 'x')
  54.     tmp = 16, s += 2; /* starts with 0x or 0X - hence hex */
  55.       else
  56.     tmp = 8;    /* starts with 0 - hence octal */
  57.       if (base==0)
  58.     base = (int)tmp;
  59.     }
  60.  
  61.   maxdiv = ULONG_MAX / base;
  62.   maxrem = ULONG_MAX % base;
  63.  
  64.   while ((digit = *s) != '\0')
  65.     {
  66.       if (digit >= '0' && digit < ('0'+base))
  67.     digit -= '0';
  68.       else
  69.     if (base > 10)
  70.       {
  71.         if (digit >= 'a' && digit < ('a'+(base-10)))
  72.           digit = digit - 'a' + 10;
  73.         else if (digit >= 'A' && digit < ('A'+(base-10)))
  74.           digit = digit - 'A' + 10;
  75.         else
  76.           break;
  77.       }
  78.     else
  79.       break;
  80.       did_conversion = 1;
  81.       if (total > maxdiv
  82.       || (total == maxdiv && digit > maxrem))
  83.     overflow = 1;
  84.       total = (total * base) + digit;
  85.       s++;
  86.     }
  87.   if (overflow)
  88.     {
  89.       errno = ERANGE;
  90.       if (ptr != NULL)
  91.     *ptr = (char *)s;
  92.       return (ULONG_MAX);
  93.     }
  94.   if (ptr != NULL)
  95.     *ptr = (char *) ((did_conversion) ? (char *)s : (char *)start);
  96.   return negate ? -total : total;
  97. }
  98.